home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / demos / hotkeyed.exe / HOTKEYED.C next >
C/C++ Source or Header  |  1992-04-13  |  29KB  |  938 lines

  1. //**************************************************************************
  2. //
  3. //  APPLICATION: 
  4. //      HotKeyEd.exe                                               
  5. //
  6. //  FILE:
  7. //      hotkeyed.c
  8. //
  9. //  AUTHOR:
  10. //      Irfan Gowani - Windows Developer Support,
  11. //                     Microsoft Product Support Services.
  12. //
  13. //  CREATION DATE:
  14. //      2-25-92
  15. //    
  16. //
  17. //  PURPOSE:
  18. //      This application demonstrates the implementation of a shortcut key
  19. //      (hot key) edit control.  The application contains a dialog box that
  20. //      allows the user to specify which hot key the application will use. 
  21. //      This dialog box uses a subclasses edit control to display the name
  22. //      of the hot key as it is entered.  The edit control checks that the 
  23. //      that the hotkey is valid before displaying it, and will not allow 
  24. //      the user to enter invalid hot keys.  GetKeyNameText() is used to get
  25. //      the names of the keys. 
  26. //
  27. //      When the user enters a valid shortcut key, it also lets the user 
  28. //      install that shortcut key.  To install the shortcut key, the app 
  29. //      uses the Windows 3.1 hook function SetWindowsHookEx() to install 
  30. //      a task specific keyboard hook.  The shortcut key can also be 
  31. //      removed by the user by menu selection or exiting the app.
  32. //
  33. //      When the shortcut key is installed, the caption is flashed to let 
  34. //      the user know that a hot key has been installed.  The caption keeps 
  35. //      on flashing until the removal of the shortcut key.  When the shortcut 
  36. //      key is pressed by the user, the main window's background color is
  37. //      toggled.
  38. //
  39. //      A shortcut key must have an ALT or/and CTRL modifier.  A shift can 
  40. //      also be specified but not by itself.  To erase a key combination from 
  41. //      the edit control, use BACKSPACE or enter another key combination.
  42. //      ESC, ENTER, TAB, SPACEBAR, and PRINT SCREEN keys are not allowed.
  43. //
  44. //
  45. //  FUNCTIONS:                                                              
  46. //
  47. //  WinMain()            - Registers a window class.
  48. //                       - Creates the main window.
  49. //                       - Enters the message loop.                                
  50. //                       
  51. //  MainWndProc()        - Processes the main window's messages.                       
  52. //
  53. //  HotKeyEditProc()     - Processes the Shortcut edit control's messages.
  54. // 
  55. //  AboutDlgProc()       - Processes the "About" dialog's messages.                  
  56. // 
  57. //  HotKeyEditDlgProc()  - Processes the HotKeyEdit" dialog messages.
  58. //
  59. //  HandleKeyDowns()     - Handles key downs for the shortcut key edit control.
  60. //
  61. //  HandleKeyUps()       - Handles key ups for the shortcut key edit control.
  62. //
  63. //  InstallHotKey()      - Installs keyboard hook.
  64. //
  65. //  RemoveHotKey()       - Removes the keyboard hook.
  66. //
  67. //  HotKeyHookCallback() - Keyboard hook callback.
  68. //
  69. //  DisplayHotKey()      - Creates and displays the shortcut key string.
  70. //
  71. //  DoErasingStuff()     - Initializes the shortcut key structure and
  72. //                         blanks-out the shortcut key edit control.
  73. //
  74. //
  75. //  Copyright (c) 1992 Microsoft Corporation. All rights reserved.
  76. //
  77. //**************************************************************************
  78.  
  79. #include <windows.h>
  80. #include "HotKeyEd.h"
  81.  
  82. HANDLE          ghInst;                 // Application's instance handle
  83. FARPROC         glpOldHotKeyEditProc;   // Original function address of the edit control
  84. HWND            ghwndMain;              // Handle to the main window
  85. HOTKEYSTRUCT    ghksHotKey;             // Shortcut key info
  86. HHOOK           ghHotKeyHook = 0;       // Shortcut key hook
  87. BOOL            gbWindowNotActive;      // Caption's state for flashing
  88.  
  89. //**************************************************************************
  90. //
  91. //  WinMain()                                                     
  92. //
  93. //  PURPOSE:                                                                
  94. //      This function registers a window class, creates
  95. //      the main window, and enters the message loop.
  96. //
  97. //  FUNCTION CALLS:
  98. //      None
  99. //
  100. //  GLOBAL VARIABLES MODIFIED:
  101. //      ghwndMain
  102. //      ghInst
  103. //
  104. //**************************************************************************
  105.  
  106. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  107.                     LPSTR lpCmdLine,  int nCmdShow)
  108. {
  109.     MSG         msg;
  110.     WNDCLASS    wc;
  111.  
  112.     if (!hPrevInstance)
  113.     {
  114.         wc.style = NULL;
  115.         wc.lpfnWndProc = MainWndProc;
  116.         wc.cbClsExtra = 0;
  117.         wc.cbWndExtra = 0;
  118.         wc.hInstance = hInstance;
  119.         wc.hIcon = LoadIcon (hInstance, "HotKeyEditIcon");
  120.         wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  121.         wc.hbrBackground = (HBRUSH) COLOR_WINDOW + 1;
  122.         wc.lpszMenuName =  "HotKeyEditMenu";
  123.         wc.lpszClassName = "HotKeyEditWClass";
  124.  
  125.         if (!RegisterClass (&wc))
  126.             return (FALSE);
  127.     } // if
  128.  
  129.     ghwndMain = CreateWindow ("HotKeyEditWClass",
  130.                               "Shortcut Edit and Install Sample - Shortcut Key = None",
  131.                               WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  132.                               CW_USEDEFAULT,
  133.                               CW_USEDEFAULT,
  134.                               CW_USEDEFAULT,
  135.                               CW_USEDEFAULT,
  136.                               NULL,
  137.                               NULL,
  138.                               hInstance,
  139.                               NULL);
  140.  
  141.     if (!ghwndMain)
  142.         return (FALSE);
  143.  
  144.     ghInst = hInstance;
  145.  
  146.     while (GetMessage (&msg,
  147.                         NULL,
  148.                         NULL,
  149.                         NULL))
  150.     {
  151.         TranslateMessage (&msg);
  152.         DispatchMessage (&msg);
  153.     } // while
  154.  
  155.     return (msg.wParam);
  156. } // WinMain()
  157.  
  158.  
  159. //**************************************************************************
  160. //
  161. //  WNDPROC:
  162. //      MainWndProc()                                                     
  163. //
  164. //  PURPOSE:                                                                
  165. //      This function handles messages belonging to the main window.
  166. //      It lets the user edit, install, and remove a shortcut key; and it
  167. //      also displays the About dialog box.
  168. //
  169. //  MESSAGES:
  170. //
  171. //      WM_CREATE:  Creates a gray and a red brush, and sets gray brush 
  172. //                  as the background brush of the main window.
  173. //
  174. //      WM_HOTKEY:  A private messages sent by the hook callback when
  175. //                  the shortcut key is pressed.  Background brush is toggled.
  176. //
  177. //      WM_COMMAND: Menu options.
  178. //
  179. //      WM_DESTROY: Shortcut key hook is removed, the second brush is deleted,
  180. //                  and PostQuitMessage().
  181. //
  182. //  FUNCTION CALLS:
  183. //      RemoveHotKey()
  184. //      HotKeyEditDlgProc() - Indirectly
  185. //      AboutDlgProc()      - Indirectly
  186. //
  187. //  CALLED BY:
  188. //      Windows
  189. //
  190. //  GLOBAL VARIABLES MODIFIED:
  191. //      gbWindowNotActive
  192. //
  193. //**************************************************************************
  194.  
  195. long FAR PASCAL MainWndProc (HWND hWnd,   unsigned uMessage,
  196.                              WORD wParam, LONG lParam)
  197. {
  198.             FARPROC lpDialogProc;
  199.     static  HBRUSH  hbrGray, hbrRed;
  200.     static  BOOL    bGrayBackground;
  201.     static  HMENU   hMenu;
  202.  
  203.     switch (uMessage)
  204.     {
  205.         case WM_CREATE:
  206.             hbrGray = CreateSolidBrush (RGB (192, 192, 192));
  207.             hbrRed  = CreateSolidBrush (RGB (255, 0, 0));
  208.  
  209.             SetClassWord (hWnd, GCW_HBRBACKGROUND, hbrGray);
  210.             bGrayBackground = TRUE;
  211.  
  212.             hMenu = GetMenu (hWnd);
  213.  
  214.             break;
  215.  
  216.         case WM_HOTKEY:   // Our private message
  217.  
  218.             // Toggle the color - Gray/Red
  219.  
  220.             if (bGrayBackground)
  221.                 SetClassWord (hWnd, GCW_HBRBACKGROUND, hbrRed);
  222.             else
  223.                 SetClassWord (hWnd, GCW_HBRBACKGROUND, hbrGray);
  224.  
  225.             InvalidateRect (hWnd, NULL, TRUE);
  226.             UpdateWindow (hWnd);
  227.  
  228.             bGrayBackground = !bGrayBackground;
  229.  
  230.             break;
  231.  
  232.         case WM_TIMER:
  233.             if (wParam == HOTKEY_TIMER)
  234.                 gbWindowNotActive = FlashWindow (hWnd, TRUE);
  235.  
  236.             break;
  237.  
  238.         case WM_COMMAND:
  239.             switch (wParam)
  240.             {
  241.                 case IDM_EDITINSTALLHOTKEY:
  242.                     lpDialogProc = MakeProcInstance (HotKeyEditDlgProc, ghInst);
  243.  
  244.                     // If the user doesn't install the shortcut key...
  245.  
  246.                     if (DialogBox (ghInst,
  247.                                    "HotKeyEditBox",
  248.                                    hWnd,
  249.                                    lpDialogProc))
  250.                         EnableMenuItem (hMenu, IDM_REMOVEHOTKEY,
  251.                                         MF_BYCOMMAND | MF_ENABLED);
  252.  
  253.                     FreeProcInstance (lpDialogProc);
  254.  
  255.                     break;
  256.  
  257.                 case IDM_REMOVEHOTKEY:
  258.                     RemoveHotKey ();
  259.  
  260.                     EnableMenuItem (hMenu, IDM_REMOVEHOTKEY,
  261.                                  MF_BYCOMMAND | MF_GRAYED);
  262.  
  263.                     break;
  264.  
  265.                 case IDM_ABOUT:
  266.                     lpDialogProc = MakeProcInstance (AboutDlgProc, ghInst);
  267.                     DialogBox (ghInst,
  268.                                 "AboutBox",
  269.                                 hWnd,
  270.                                 lpDialogProc);
  271.                     FreeProcInstance (lpDialogProc);
  272.  
  273.                     break;
  274.  
  275.                 default:
  276.                     return (DefWindowProc (hWnd, uMessage, wParam, lParam));
  277.             } // switch (wParam)
  278.             break;
  279.  
  280.         case WM_DESTROY:
  281.             RemoveHotKey ();
  282.  
  283.             // Delete the brush that is not selected
  284.             if (bGrayBackground)
  285.                 DeleteObject (hbrRed);
  286.             else
  287.                 DeleteObject (hbrGray);
  288.  
  289.             PostQuitMessage (0);
  290.  
  291.             break;
  292.  
  293.         default:
  294.             return (DefWindowProc (hWnd, uMessage, wParam, lParam));
  295.     } // switch (uMessage)
  296.  
  297.     return (0);
  298.  
  299. } // MainWndProc()
  300.  
  301.  
  302. //**************************************************************************
  303. //
  304. //  WNDPROC:
  305. //      HotKeyEditProc()
  306. //
  307. //  PURPOSE:
  308. //
  309. //      This is a subclassed function that handles messages belonging to 
  310. //      the Shortcut edit control.
  311. //
  312. //  MESSAGES:
  313. //
  314. //      WM_KEYDOWN:
  315. //          WM_SYSKEYDOWN:
  316. //          Calls HandleKeyDowns().
  317. //
  318. //          WM_KEYUP:
  319. //          WM_SYSKEYUP:
  320. //          WM_SYSCHAR:
  321. //          WM_CHAR:
  322. //          Calls HandleKeyUps().
  323. //
  324. //  FUNCTION CALLS:
  325. //      HandleKeyDowns()
  326. //      HandleKeyUps()
  327. //
  328. //  CALLED BY:
  329. //      Windows
  330. //
  331. //**************************************************************************
  332.  
  333. long FAR PASCAL HotKeyEditProc (HWND hHotKeyEdit, unsigned uMessage,
  334.                                 WORD wParam,      LONG lParam)
  335. {
  336.     static  WORD    wModifierKeys;
  337.  
  338.     switch (uMessage)
  339.     {
  340.         case WM_KEYDOWN:
  341.         case WM_SYSKEYDOWN:
  342.             return (HandleKeyDowns (hHotKeyEdit, uMessage, wParam,
  343.                                     lParam, &wModifierKeys));
  344.  
  345.         case WM_KEYUP:
  346.         case WM_SYSKEYUP:
  347.         case WM_SYSCHAR:
  348.         case WM_CHAR:
  349.             return (HandleKeyUps (hHotKeyEdit, uMessage, wParam,
  350.                                   lParam, wModifierKeys));
  351.  
  352.                 default:
  353.                         return (CallWindowProc (glpOldHotKeyEditProc, hHotKeyEdit, uMessage,
  354.                                     wParam, lParam));
  355.  
  356.     } // switch (uMessage)
  357.  
  358.     return (0);
  359.  
  360. } // HotKeyEditProc
  361.  
  362.  
  363. //**************************************************************************
  364. //
  365. //  DIALOGPROC:
  366. //      AboutDlgProc()                                                     
  367. //
  368. //  PURPOSE:                                                                
  369. //      This function handles messages belonging to the "About" dialog box.
  370. //      The only message that it looks for is WM_COMMAND, indicating that the
  371. //      user has pressed the "OK" button or hit <Esc>.  When this happens, 
  372. //      it takes down the dialog box.
  373. //
  374. //  MESSAGES:
  375. //  
  376. //      WM_INITDIALOG:  return (TRUE).
  377. //
  378. //      WM_COMMAND:     Dialog is terminated upon Cancel or OK.
  379. //
  380. //  FUNCTION CALLS:
  381. //      None
  382. //
  383. //  CALLED BY:
  384. //      MainWndProc() - Indirectly
  385. //
  386. //**************************************************************************
  387.  
  388. BOOL FAR PASCAL AboutDlgProc (HWND hDlg,   unsigned uMessage,
  389.                        WORD wParam, LONG lParam)
  390. {
  391.     switch (uMessage)
  392.     {
  393.         case WM_INITDIALOG:
  394.             return (TRUE);
  395.  
  396.         case WM_COMMAND:
  397.             switch (wParam)
  398.             {
  399.                 case IDOK:
  400.                 case IDCANCEL:
  401.                     EndDialog (hDlg, TRUE);
  402.                     return (TRUE);
  403.  
  404.                 default:
  405.                     break;
  406.             } /* switch (wParam) */
  407.     } // switch (uMessage)
  408.  
  409.     return (FALSE);
  410.  
  411. } // AboutDlgProc()
  412.  
  413.  
  414. //**************************************************************************
  415. //
  416. //  DIALOGPROC:
  417. //      HotKeyEditDlgProc()                                                     
  418. //
  419. //  PURPOSE:                                                                
  420. //                                                                           
  421. //      This function handles messages belonging to the "HotKeyEdit" dialog
  422. //      box.  
  423. //
  424. //  MESSAGES:
  425. //  
  426. //      WM_INITDIALOG:  Subclasses the shortcut key edit control.
  427. //
  428. //      WM_COMMAND:     - Installs a valid shortcut key.  
  429. //                      - Dialog is terminated upon Cancel or Install.
  430. //                      - Upon Cancel, EndDialog() is returned with a FALSE;
  431. //                        so the calling function would know that the hook
  432. //                        was not installed.
  433. //
  434. //  FUNCTION CALLS:
  435. //      None
  436. //
  437. //  CALLED BY:
  438. //      MainWndProc() - Indirectly
  439. //  
  440. //  GLOBAL VARIABLES MODIFIED:
  441. //      glpOldHotKeyEditProc
  442. //
  443. //**************************************************************************
  444.  
  445. BOOL FAR PASCAL HotKeyEditDlgProc (HWND hDlg,   unsigned uMessage,
  446.                                    WORD wParam, LONG lParam)
  447. {
  448.             FARPROC lpHotKeyEditProc;
  449.     static  HWND    hHotKeyEdit;
  450.  
  451.     switch (uMessage)
  452.     {
  453.         case WM_INITDIALOG:
  454.             hHotKeyEdit = GetDlgItem (hDlg, IDD_HOTKEYEDIT);
  455.  
  456.                 lpHotKeyEditProc = MakeProcInstance ((FARPROC) HotKeyEditProc,
  457.                                                   ghInst);
  458.  
  459.                 glpOldHotKeyEditProc = (FARPROC)
  460.                                     SetWindowLong (hHotKeyEdit,
  461.                                                    GWL_WNDPROC,
  462.                                                    (DWORD) lpHotKeyEditProc);
  463.             return (TRUE);
  464.  
  465.         case WM_COMMAND:
  466.             switch (wParam)
  467.             {
  468.                 case IDD_INSTALL:
  469.                     GetWindowText (hHotKeyEdit,
  470.                                    (LPSTR) ghksHotKey.szText,
  471.                                    STR_LEN);
  472.  
  473.                     InstallHotKey ();
  474.  
  475.                     EndDialog (hDlg, TRUE);
  476.                     return (TRUE);
  477.  
  478.                 case IDCANCEL:
  479.                     // Return FALSE since the user canceled it
  480.                     EndDialog (hDlg, FALSE);
  481.                     return (TRUE);
  482.  
  483.                 default:
  484.                     break;
  485.             } /* switch (wParam) */
  486.     } // switch (uMessage)
  487.  
  488.     return (FALSE);
  489.  
  490. } // HotKeyEditDlgProc()
  491.  
  492.  
  493.  
  494. //***************************************************************************
  495. //
  496. //  FUNCTION:
  497. //      HandleKeyDowns()
  498. //
  499. //  PURPOSE:
  500. //      This function handles key downs for the shortcut key edit control.
  501. //      It sets and displays the shortcut key in the edit control.
  502. //      
  503. //
  504. //  PARAMETERS:
  505. //
  506. //      IN:
  507. //          hHotKeyEdit    - Shortcut key's edit control's handle
  508. //          uMessage       - Control's message
  509. //          wParam         - Message information
  510. //          lParam         - Additional message information
  511. //          pwModifierKeys - N/A
  512. //
  513. //      OUT:
  514. //          pwModifierKeys - Modifier (ALT, CONTROL, SHIFT) bits
  515. //                           if they are pressed
  516. //
  517. //
  518. //  RETURN VALUE:
  519. //      Appropriate value if key belongs to Windows; otherwise 0.
  520. //
  521. //  FUNCTION CALLS:
  522. //      DoErasingStuff()
  523. //      DisplayHotKey()
  524. //
  525. //  CALLED BY:
  526. //      MainWndProc()
  527. //
  528. //***************************************************************************
  529.  
  530. long HandleKeyDowns (HWND hHotKeyEdit, unsigned uMessage,  WORD  wParam,
  531.                     LONG  lParam,      PWORD pwModifierKeys)
  532. {
  533.     *pwModifierKeys = 0;
  534.  
  535.     // Set wModifierKeys according to the modifier keys down
  536.  
  537.     if (GetKeyState (VK_CONTROL) & 0x1000)
  538.         *pwModifierKeys |= CONTROL_BIT;
  539.  
  540.     if (GetKeyState (VK_SHIFT) & 0x1000)
  541.         *pwModifierKeys |= SHIFT_BIT;
  542.  
  543.     if (lParam & 0x20000000)
  544.         *pwModifierKeys |= MENU_BIT;
  545.  
  546.     // If the keys are for the dialog box or Windows, pass them
  547.  
  548.     if (wParam == VK_TAB || wParam == VK_ESCAPE
  549.     || wParam == VK_RETURN || wParam == VK_SPACE)
  550.     {
  551.         DoErasingStuff (hHotKeyEdit);
  552.             return (CallWindowProc (glpOldHotKeyEditProc, hHotKeyEdit, uMessage,
  553.                                 wParam, lParam));
  554.     }
  555.     else if (wParam == VK_BACK && *pwModifierKeys == 0)
  556.     {
  557.         // If BACKSPACE, then erase the edit control and the shortcut key structure;
  558.         // and make the INSTALL button disabled.
  559.  
  560.         DoErasingStuff (hHotKeyEdit);
  561.         EnableWindow (GetDlgItem (GetParent (hHotKeyEdit), IDD_INSTALL), FALSE);
  562.  
  563.         return (0);
  564.     }
  565.     else if (*pwModifierKeys)
  566.     {
  567.         // Display the keys but only if the modifier(s) present
  568.  
  569.         DisplayHotKey (GetParent (hHotKeyEdit), *pwModifierKeys, wParam, lParam);
  570.         return (0);
  571.  
  572.     }
  573.  
  574. } // HandleKeyDowns()
  575.  
  576.  
  577. //***************************************************************************
  578. //
  579. //  FUNCTION:
  580. //      HandleKeyUps()
  581. //
  582. //  PURPOSE:
  583. //      This function handles key ups for the shortcut key edit control.
  584. //      If the shortcut key is not valid, it blanks-out the edit control.w
  585. //
  586. //  PARAMETERS:
  587. //
  588. //      IN:
  589. //          hHotKeyEdit   - Shortcut key's edit control's handle
  590. //          uMessage      - Control's message
  591. //          wParam        - Message information
  592. //          lParam        - Additional message information
  593. //          wModifierKeys - ALT, CONTROL, SHIFT bits if they are pressed
  594. //
  595. //      OUT:
  596. //          N/A
  597. //
  598. //  RETURN VALUE:
  599. //
  600. //
  601. //  FUNCTION CALLS:
  602. //      DoErasingStuff()
  603. //
  604. //  CALLED BY:
  605. //      MainWndProc()
  606. //
  607. //***************************************************************************
  608.  
  609. long HandleKeyUps (HWND hHotKeyEdit, unsigned uMessage,     WORD  wParam,
  610.                    LONG  lParam,     WORD     wModifierKeys)
  611.  
  612. {
  613.     switch (wParam)
  614.     {
  615.         // If it's a restricted key, then pass it to windows
  616.         case VK_RETURN:
  617.         case VK_ESCAPE:
  618.         case VK_TAB:
  619.                         return (CallWindowProc (glpOldHotKeyEditProc, hHotKeyEdit, uMessage,
  620.                                     wParam, lParam));
  621.  
  622.             default:
  623.                 // If only the modifier keys were pressed, 
  624.                 // OR
  625.                 // If SHIFT is the only modifier key with a valid key,
  626.                 // then erase and initialize the edit control
  627.                 if (ghksHotKey.uKey == 0 ||
  628.                 (wModifierKeys == SHIFT_BIT && uMessage == WM_KEYUP))
  629.                     DoErasingStuff (hHotKeyEdit);
  630.  
  631.                 return (0);
  632.     }
  633. } // HandleLeyUps()
  634.  
  635. //***************************************************************************
  636. //
  637. //  FUNCTION:
  638. //      InstallHotKey()
  639. //
  640. //  PURPOSE:
  641. //      - Installs a task specific keyboard hook.
  642. //      - Sets timer to flash window caption.
  643. //      - Sets window caption to reflect the new shortcut key.
  644. //
  645. //  PARAMETERS:
  646. //      void
  647. //
  648. //  RETURN VALUE:
  649. //      void
  650. //
  651. //  FUNCTION CALLS:
  652. //      None
  653. //
  654. //  CALLED BY:
  655. //      HotKeyEditDlgProc()
  656. //
  657. //  GLOBAL VARIABLES MODOFIED:
  658. //      ghHotKeyHook
  659. //
  660. //***************************************************************************
  661.  
  662. void InstallHotKey (void)
  663. {
  664.     char    szCaption [CAPTION_LEN];
  665.  
  666.     // If there is already a hook installed, then don't do it again.
  667.     if (!ghHotKeyHook)
  668.         ghHotKeyHook = SetWindowsHookEx (WH_KEYBOARD,
  669.                                    (FARPROC) HotKeyHookCallback,
  670.                                    ghInst,
  671.                                    GetCurrentTask ());
  672.     wsprintf ((LPSTR) szCaption,
  673.               "Shortcut Edit and Install Sample - Shortcut Key = %s",
  674.               (LPSTR) ghksHotKey.szText);
  675.  
  676.     SetTimer (ghwndMain, HOTKEY_TIMER, TIME_OUT, NULL);
  677.  
  678.     SetWindowText (ghwndMain, (LPSTR) szCaption);
  679.  
  680. } // InstallHotKey()
  681.  
  682. //***************************************************************************
  683. //
  684. //  WNDPROC:
  685. //      RemoveHotKey()
  686. //
  687. //  PURPOSE:
  688. //      - Removes the keyboard hook.
  689. //      - Sets the window caption to refelect no shortcut key.
  690. //      - Kills the timer that's used for flashing the window caption
  691. //      
  692. //
  693. //  PARAMETERS:
  694. //      void
  695. //
  696. //  RETURN VALUE:
  697. //      void
  698. //
  699. //  FUNCTION CALLS:
  700. //      None
  701. //
  702. //  CALLED BY:
  703. //      MainWndProc()
  704. //
  705. //  GLOBAL VARIABLES MODOFIED:
  706. //      ghHotKeyHook
  707. //
  708. //***************************************************************************
  709.  
  710. void RemoveHotKey (void)
  711. {
  712.     if (ghHotKeyHook)
  713.         UnhookWindowsHookEx (ghHotKeyHook);
  714.  
  715.     ghHotKeyHook = 0;
  716.  
  717.     SetWindowText (ghwndMain,
  718.                    "Shortcut Edit and Install Sample - Shortcut Key = None");
  719.  
  720.     KillTimer (ghwndMain, HOTKEY_TIMER);
  721.  
  722.     // Highlight the caption if now it's inactive
  723.     if (gbWindowNotActive)
  724.         FlashWindow (ghwndMain, FALSE);
  725.  
  726. } // RemoveHotKey()
  727.  
  728.  
  729. //***************************************************************************
  730. //
  731. //  FUNCTION:
  732. //      DisplayHotKey()
  733. //
  734. //  PURPOSE:
  735. //      - Creates the shortcut key string and displays it.
  736. //      - Sets the global shortcut key structure.
  737. //
  738. //  PARAMETERS:
  739. //
  740. //      IN:
  741. //          hDlg          - Shortcut Key edit control's parent dialog
  742. //          wModifierKeys - ALT, CONTROL, SHIFT bits if they are pressed
  743. //          wKeyNum       - The pressed key
  744. //          lKeyInfo      - Additional key info
  745. //
  746. //      OUT:
  747. //          N/A
  748. //
  749. //  RETURN VALUE:
  750. //      void
  751. //
  752. //  FUNCTION CALLS:
  753. //      None
  754. //
  755. //  CALLED BY:
  756. //      HandleKeyDowns()
  757. //
  758. //  GLOBAL VARIABLES MODIFIED:
  759. //      ghksHotKey
  760. //
  761. //***************************************************************************
  762.  
  763. void DisplayHotKey (HWND hDlg,    WORD wModifierKeys,
  764.                     WORD wKeyNum, LONG lKeyInfo)
  765. {
  766.     char    szHotKey [STR_LEN];
  767.     char    szKeyName [STR_LEN];
  768.     int     iHotKeyStrLen;
  769.     HWND    hHotKeyEdit = GetDlgItem (hDlg, IDD_HOTKEYEDIT);
  770.  
  771.     szHotKey [0] = 0;
  772.  
  773.     // Disable the button if it was enabled.
  774.     EnableWindow (GetDlgItem (hDlg, IDD_INSTALL), FALSE);
  775.  
  776.     // Create the string to display the modifier keys.
  777.  
  778.     if (wModifierKeys & MENU_BIT)
  779.         wsprintf ((LPSTR) szHotKey, "Alt");
  780.  
  781.     if (wModifierKeys & CONTROL_BIT)
  782.         if (wModifierKeys & MENU_BIT)
  783.             lstrcat ((LPSTR) szHotKey, (LPSTR) "+Ctrl");
  784.         else
  785.             lstrcat ((LPSTR) szHotKey, (LPSTR) "Ctrl");
  786.  
  787.     if (wModifierKeys & SHIFT_BIT)
  788.         if (wModifierKeys & MENU_BIT || wModifierKeys & CONTROL_BIT)
  789.             lstrcat ((LPSTR) szHotKey, (LPSTR) "+Shift");
  790.         else
  791.             lstrcat ((LPSTR) szHotKey, (LPSTR) "Shift");
  792.  
  793.  
  794.     // Display modifier keys
  795.  
  796.     SetWindowText (hHotKeyEdit, (LPSTR) szHotKey);
  797.     
  798.     // Save the keys
  799.  
  800.     ghksHotKey.wModifierKeys = wModifierKeys;
  801.     ghksHotKey.uKey = 0;
  802.  
  803.     // Set the cursor at the end of the text
  804.     iHotKeyStrLen = lstrlen ((LPSTR) szHotKey);
  805.  
  806.     SendMessage (hHotKeyEdit, EM_SETSEL, 0, 
  807.                 MAKELONG (iHotKeyStrLen, iHotKeyStrLen));
  808.  
  809.  
  810.     // Add the character key and then display it.
  811.  
  812.     if (GetKeyNameText (lKeyInfo, (LPSTR) szKeyName, STR_LEN)
  813.     && (wKeyNum != VK_MENU && wKeyNum != VK_CONTROL && wKeyNum != VK_SHIFT))
  814.     {
  815.         lstrcat ((LPSTR) szHotKey, (LPSTR) "+");
  816.         lstrcat ((LPSTR) szHotKey, (LPSTR) szKeyName);
  817.  
  818.         // Save the character key
  819.  
  820.         ghksHotKey.uKey = wKeyNum;
  821.  
  822.         // Display rest of the shortcut key
  823.  
  824.         SetWindowText (hHotKeyEdit, (LPSTR) szHotKey);
  825.  
  826.         // Let the user Install the shortcut key
  827.         // if it's a valid shortcut key
  828.         if (wModifierKeys != SHIFT_BIT)
  829.             EnableWindow (GetDlgItem (hDlg, IDD_INSTALL), TRUE);
  830.  
  831.         // Set the cursor at the end of the text
  832.         iHotKeyStrLen = lstrlen ((LPSTR) szHotKey);
  833.  
  834.         SendMessage (hHotKeyEdit, EM_SETSEL, 0, 
  835.                     MAKELONG (iHotKeyStrLen, iHotKeyStrLen));
  836.     }
  837.  
  838. } // DisplayHotKey()
  839.  
  840. //**************************************************************************
  841. //
  842. //  CALLBACK:
  843. //      HotKeyHookCallback()
  844. //
  845. //  PURPOSE:
  846. //
  847. //      This function is a keyboard filter for this application.
  848. //      It checks whethter the user-specified shortcut key has been pressed
  849. //      or not.  In case of the shortcut key, the main window is sent a private
  850. //      message so it can change the main-window background color.
  851. //
  852. //  GLOBAL VARIABLES MODIFIED:
  853. //      ghksHotKey
  854. //
  855. //**************************************************************************
  856.  
  857. DWORD FAR PASCAL HotKeyHookCallback (int     nCode,
  858.                                      WORD    wParam,
  859.                                      DWORD   lParam)
  860. {
  861.     // If the key pressed is part of the shortcut key
  862.     // and nCode is ours to process, then look for 
  863.     // modifier keys for the shortcut key.  If the shortcut key
  864.     // was pressed, then post the main window a message
  865.     // so it should change the main-window background color.
  866.  
  867.     if (nCode == HC_ACTION && ghksHotKey.uKey == wParam)
  868.     {
  869.         // Skip if the key was released or if it's a repeat
  870.         if (lParam & 0x80000000 || lParam & 0x40000000)
  871.             goto Exit;
  872.  
  873.         // Check to see if ALT is part of the shortcut key and pressed
  874.         if (ghksHotKey.wModifierKeys & MENU_BIT)
  875.             if (!(lParam & 0x20000000))
  876.                 goto Exit;
  877.         
  878.         // Check to see if CONTROL is part of the shortcut key and pressed
  879.         if (ghksHotKey.wModifierKeys & CONTROL_BIT)
  880.             if (!(GetKeyState (VK_CONTROL) & 0x1000))
  881.                 goto Exit;
  882.  
  883.         // Check to see if SHIFT is part of the shortcut key and pressed
  884.         if (ghksHotKey.wModifierKeys & SHIFT_BIT)
  885.             if (!(GetKeyState (VK_SHIFT) & 0x1000))
  886.                 goto Exit;
  887.  
  888.         PostMessage (ghwndMain, WM_HOTKEY, 0, 0L);
  889.     }
  890.  
  891. Exit:
  892.  
  893.     return (CallNextHookEx (ghHotKeyHook,
  894.                             nCode,
  895.                             wParam,
  896.                             (LONG)lParam));
  897. } // HotKeyHookCallback()
  898.  
  899.  
  900. //***************************************************************************
  901. //
  902. //  FUNCTION:
  903. //      DoErasingStuff()
  904. //
  905. //  PURPOSE:
  906. //      - Blanks-out the shortcut key edit control.
  907. //      - Initializes the global shortcut key structure.
  908. //
  909. //  PARAMETERS:
  910. //
  911. //      IN:
  912. //          hHotKeyEdit  - Shortcut key's edit control's handle
  913. //
  914. //      OUT:
  915. //          N/A
  916. //
  917. //  RETURN VALUE:
  918. //      void
  919. //
  920. //  FUNCTION CALLS:
  921. //      None
  922. //
  923. //  CALLED BY:
  924. //      HandleKeyDowns()
  925. //      HandleKeyUps()
  926. //
  927. //  GLOBAL VARIABLES MODIFIED:
  928. //      ghksHotKey
  929. //
  930. //***************************************************************************
  931.  
  932. void DoErasingStuff (HWND hHotKeyEdit)
  933. {
  934.     SetWindowText (hHotKeyEdit, (LPSTR) '\0');
  935.     ghksHotKey.wModifierKeys = 0;
  936.     ghksHotKey.uKey = 0;
  937. } // DoErasingStuff()
  938.